package QC.MessageBox.common;

import QC.MessageBox.exceptions.HttpClientException;
import QC.MessageBox.exceptions.ParamException;
import com.ning.http.client.*;
import com.ning.http.client.multipart.FilePart;
import com.ning.http.client.multipart.Part;
import com.ning.http.client.multipart.StringPart;
import io.vertx.core.Future;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.apache.http.HttpException;

import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Created by Andaren on 2017/5/11.
 * Used for: http工具类
 */
public class HttpUtils {

    /**
     * 回复微信用户时，如果有多媒体资源需要先上传多媒体资源
     * @param client            // 异步请求
     * @param queryURL          // 请求地址
     * @param file              // 多媒体文件
     * @param paramMap          // 请求的form表单参数
     * @return
     * @throws HttpClientException
     * @throws HttpException
     * @throws IOException
     */
    public static Future<JsonObject> postWithFileListAndParamMap(AsyncHttpClient client, String queryURL,
                                                                 File file, Map<String, String> paramMap)
            throws HttpClientException, HttpException, IOException {
        if(queryURL == null) {
            throw new HttpClientException("queryURL is null.");
        }
        if(file == null) {
            throw new HttpClientException("fileList is null.");
        }
        if(paramMap == null || paramMap.size() == 0) {
            throw new HttpClientException("paramMap is null.");
        }
        // 文件大小不允许超过2M
        Long maxfileLength = Long.valueOf(2 * 1024 * 1024);
        if (file.length() > maxfileLength) {
            throw new HttpClientException("file is too big [size="+file.length()+"] when allow size is " + maxfileLength);
        }
        return executeByPostWithFileListAndParamMap(client, queryURL, file, paramMap);
    }

    private static Future<JsonObject> executeByPostWithFileListAndParamMap (AsyncHttpClient client, String queryURL, File file, Map<String,String> paramsMap) throws HttpException, IOException, HttpClientException {
        Future<JsonObject> execuFut = Future.future();
        if(queryURL != null) {
            try {
                RequestBuilder requestBuilder = new RequestBuilder();
                // FilePart (单文件或者多文件)
                Part filePart = new FilePart(file.getName(), file);
                requestBuilder.addBodyPart(filePart);

                // StringPart
                if(paramsMap != null ) {
                    Set<Map.Entry<String, String>> entrySet = paramsMap.entrySet();
                    Iterator<Map.Entry<String, String>> it = entrySet.iterator();
                    while(it.hasNext()) {
                        Map.Entry<String, String> entry = it.next();
                        Part stringPart = new StringPart(entry.getKey(),entry.getValue());
                        requestBuilder.addBodyPart(stringPart);
                    }
                }

                // 添加RequestHeader，key
                requestBuilder.addHeader("Content-type", "multipart/form-data; charset=UTF-8");
                requestBuilder.setMethod("POST");
                // 添加URL
                requestBuilder.setUrl(queryURL);

                // request
                Request request = requestBuilder.build();

                // 提交
                client.executeRequest(request, new AsyncCompletionHandler<Void>() {
                    public Void onCompleted(Response response) throws Exception {
                        byte[] responseBody = getBytesFromInpuStream(response.getResponseBodyAsStream());
                        execuFut.complete(new JsonObject(new String(responseBody, Charset.forName("UTF-8"))));
                        return null;
                    }
                });
            } catch (Exception e) {
                throw new HttpClientException(e);
            }
        }
        return execuFut;
    }

    private static byte[] getBytesFromInpuStream(InputStream instream) throws IOException {
        ByteArrayOutputStream outstream = new ByteArrayOutputStream();
        try {
            int length;
            byte[] tmp = new byte[8096];
            while ((length = instream.read(tmp)) != -1) {
                outstream.write(tmp, 0, length);
            }
            return outstream.toByteArray();
        } finally {
            instream.close();
            outstream.close();
        }
    }

    /**
     * 通用json数据返回
     * @param response
     * @param respObj
     */
    public static void commonJsonResponse(HttpServerResponse response, Object respObj) {
        if (respObj instanceof JsonArray) {
            JsonArray respJsonArray = (JsonArray) respObj;
            response
                    .putHeader("content-type", "text/json")
                    .end(respJsonArray.encodePrettily());
        } else if (respObj instanceof JsonObject) {
            JsonObject respJson = (JsonObject) respObj;
            response
                    .putHeader("content-type", "text/json")
                    .end(respJson.encodePrettily());
        } else if (respObj instanceof String) {
            response.end(respObj.toString());
        }
    }

    /**
     * Web聊天调用回复微信消息返回
     * @param response
     * @param method
     * @param msg
     */
    public static void webTalkJsonResponse(HttpServerResponse response, String method, JsonObject msg) {
        response
                .putHeader("content-type", "text/json")
                .end(method + "(" + msg.encodePrettily() + ")");
    }

    /**
     * 分析&拼接的请求参数，组装到Map中
     *
     *  content=15215&openId=dfdsf => map.put("content", "15215").put("openId", "dfdsf")
     * @param msgStr
     * @return
     */
    public static Map<String, String> getMapFromLinkedStr(String msgStr) throws Exception {

        Map<String, String> param = new HashMap<>();
        String[] msgArray = msgStr.split("&");
        if (msgArray != null && msgArray.length > 0) {
            for (String s : msgArray) {
                String[] sa = s.split("=");
                if (sa != null && sa.length == 2) {
                    param.put(sa[0], sa[1]);
                } else {
                    throw new ParamException(s);
                }
            }
        } else {
            return null;
        }
        // URL编码解码
        for (Map.Entry entry : param.entrySet()) {
            entry.setValue(URLDecoder.decode(String.valueOf(entry.getValue()), "utf-8"));
        }
        return param;
    }

    public static void main(String args[]) {
        try {
            String[] sa = "=".split("=");
            System.out.println(sa[1]);
        } catch (Exception e) {
            //e.printStackTrace();
            System.out.println("error");
        }
        System.out.println("chengdfsfds");
    }
}
